/*
 * This file is Copyright 2002-2006 Loyola University Chicago,
 * Department of Computer Science and the Emerging Technologies Laboratory.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License via
 *    http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2006 Google Inc.
 * Modified 2006 by Benjamin Gonzalez, Loyola University Chicago
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.citep.web.gwt.widgets;

import com.citep.web.gwt.widgets.DynaTableDataProvider.RowDataAcceptor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.Label;

public class DynaTable extends Composite {

  protected class NavBar extends Composite implements ClickListener {

	public final DockPanel bar = new DockPanel();
    //public final Button gotoFirst = new Button("&lt;&lt;", this);
    //public final Button gotoNext = new Button("&gt;", this);
    //public final Button gotoPrev = new Button("&lt;", this);
	public final Label gotoNext = new Label("Next>");
	public final Label gotoPrev = new Label("<Previous");
	
    public final HTML status = new HTML();
    public final HTML message = new HTML("message");

    public NavBar() {
      setWidget(bar);
      bar.setStyleName("data_grid_nav");
      message.setStyleName("data_grid_status");

      HorizontalPanel buttons = new HorizontalPanel();
//    buttons.add(gotoFirst);
      gotoNext.setStyleName("data_grid_nav_link");
      gotoPrev.setStyleName("data_grid_nav_link");
      
      gotoNext.addClickListener(this);
      gotoPrev.addClickListener(this);
      
      buttons.add(gotoPrev);
//      buttons.add(status);
      buttons.add(gotoNext);

      bar.add(buttons, DockPanel.EAST);
      bar.setCellHorizontalAlignment(buttons, DockPanel.ALIGN_RIGHT);
//      bar.add(status, DockPanel.CENTER);
      bar.add(message, DockPanel.CENTER);
      bar.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);

      bar.setCellHorizontalAlignment(message, HasAlignment.ALIGN_CENTER);
      bar.setCellVerticalAlignment(message, HasAlignment.ALIGN_MIDDLE);
      
//      bar.setCellHorizontalAlignment(status, HasAlignment.ALIGN_RIGHT);
//      bar.setCellVerticalAlignment(status, HasAlignment.ALIGN_MIDDLE);
      bar.setCellWidth(message, "100%");

      // Initialize prev & first button to disabled.
      //
      gotoPrev.setVisible(false);
//      gotoPrev.setEnabled(false);
//		gotoFirst.setEnabled(false);
    }

    public void onClick(Widget sender) {
      if (sender == gotoNext) {
        startRow += getDataRowCount();
        refresh();
      } else if (sender == gotoPrev) {
        startRow -= getDataRowCount();
        if (startRow < 0) {
          startRow = 0;
        }
        refresh();
      } /*else if (sender == gotoFirst) {
        startRow = 0;
        refresh();
      }*/
    }

  }

  protected class RowDataAcceptorImpl implements RowDataAcceptor {
    public void accept(int startRow, String[][] data) {

      int destRowCount = getDataRowCount();
      int destColCount = grid.getCellCount(0);
      
      System.out.println("len: " + data.length + " destrowcount: " + destRowCount);
      assert (data.length <= destRowCount) : "Too many rows";

      int srcRowIndex = 0;
      int srcRowCount = data.length;
      int destRowIndex = 1; // skip navbar row
      for (; srcRowIndex < srcRowCount; ++srcRowIndex, ++destRowIndex) {
    	
        String[] srcRowData = data[srcRowIndex];
        assert (srcRowData.length == destColCount) : " Column count mismatch";
        for (int srcColIndex = 0; srcColIndex < destColCount; ++srcColIndex) {
          String cellHTML = srcRowData[srcColIndex];
          grid.setText(destRowIndex, srcColIndex, cellHTML);
        }
      }

      // Clear remaining table rows.
      //
      boolean isLastPage = false;
      for (; destRowIndex < destRowCount + 1; ++destRowIndex) {
        isLastPage = true;
        for (int destColIndex = 0; destColIndex < destColCount; ++destColIndex) {
          grid.clearCell(destRowIndex, destColIndex);
        }
      }

      clearStatusText();
      // Synchronize the nav buttons.
      //
      navbar.gotoNext.setVisible(!isLastPage);
//      navbar.gotoFirst.setEnabled(startRow > 0);
      navbar.gotoPrev.setVisible(startRow > 0);

      // Update the status message.
      //
//      setStatusText((startRow + 1) + " - " + (startRow + srcRowCount));
    }

    public void failed(Throwable caught) {
      String msg = "Failed to access data";
      if (caught != null) {
        msg += ": " + caught.getMessage();
      }
      setStatusText(msg);
    }
  }

  private DataClickListener dataClickListener;
  
  public DynaTable(DynaTableDataProvider provider, String[] columns, String gridStyleName, String headerRowStyle, String entryRowStyle, String[] columnStyles, int rowCount) {

    if (columns.length == 0) {
      throw new IllegalArgumentException(
        "expecting a positive number of columns");
    }

    if (columnStyles != null && columns.length != columnStyles.length) {
      throw new IllegalArgumentException("expecting as many styles as columns");
    }

    
    this.provider = provider;
    setWidget(outer);
    grid.setStyleName(gridStyleName);
    grid.setWidth("100%");

    outer.add(navbar, DockPanel.NORTH);
    outer.add(grid, DockPanel.CENTER);
    initTable(columns, headerRowStyle, entryRowStyle, columnStyles, rowCount);
    setStyleName("DynaTable-DynaTableWidget");
  }

  public void setDataClickListener(DataClickListener l) {
	  dataClickListener = l;
  }
  
  private void initTable(String[] columns, String headerRowStyle, String entryRowStyle, String[] columnStyles, int rowCount) {
    // Set up the header row.  It's one greater than the number of visible rows.
    //
    grid.resize(rowCount+1, columns.length);

    //listen for clicks on each row/cell, and if there is a registered dataclicklistener,
    //call it
    grid.addTableListener(new TableListener() {
    	public void onCellClicked(SourcesTableEvents e, int row, int column) {
    		if(dataClickListener != null)
    			if(row > 0) //skip the header row
    				dataClickListener.onDataElementClicked(row-1, column);
    		
    	}
    });
    
    
    if(headerRowStyle != null && headerRowStyle.length() > 0)
    	grid.getRowFormatter().setStyleName(0, headerRowStyle);
    
    for (int i = 0, n = columns.length; i < n; i++) {
      String caption = columns[i];
      final int colIndex = i;
      grid.setText(0, i, columns[i]);
    }
    
    for(int i = 1, n = rowCount+1; i < n; i++) {
    	
        if(entryRowStyle != null && entryRowStyle.length() > 0)
        	grid.getRowFormatter().setStyleName(i, entryRowStyle);
        
        if(columnStyles != null) {
	    	for(int j = 0; j < columns.length; j++) {
	    		grid.getCellFormatter().setStyleName(i, j, columnStyles[j]);
	    	}
        }
        
    }
  }

  public void setStatusText(String text) {
    navbar.message.setText(text);
    navbar.message.setVisible(true);
  }

  public void clearStatusText() {
    navbar.message.setHTML("&nbsp;");
    navbar.message.setVisible(false);
  }
  
  public int getStartRow() {
	  return startRow;
  }

  public void refresh() {
    // Disable buttons temporarily to stop the user from running off the end.
    //
//    navbar.gotoFirst.setEnabled(false);

    navbar.gotoPrev.setVisible(false);
    navbar.gotoNext.setVisible(false);

    setStatusText("Please wait...");
    provider.updateRowData(startRow, grid.getRowCount() - 1, acceptor);
  }

  public void setRowCount(int rows) {
    grid.resizeRows(rows);
  }

  private int getDataRowCount() {
    return grid.getRowCount() - 1;
  }

  private final RowDataAcceptor acceptor = new RowDataAcceptorImpl();
  private final NavBar navbar = new NavBar();
  private final DockPanel outer = new DockPanel();
  private final DynaTableDataProvider provider;
  private int startRow = 0;
  protected final Grid grid = new Grid();
}
